#pragma	once

#include <boost/asio.hpp>
#include <boost/array.hpp>

#include <Network/TcpPacket.h>

class TcpConnection;
class TcpConnectionEventHandler
{
public:
	virtual void OnConnected(TcpConnection*, int error) = 0;
	virtual void OnReceived(TcpConnection*, TcpPacket* packet, int error) = 0;
	virtual void OnSent(TcpConnection*, int error) = 0;
	virtual void OnClosed(TcpConnection*, int error) = 0;
};

class TcpConnection
{
public:
	TcpConnection(boost::asio::io_service& io_service, TcpConnectionEventHandler* eventHandler);
	TcpConnection(std::shared_ptr<boost::asio::ip::tcp::socket>& socket, TcpConnectionEventHandler* eventHandler);
	~TcpConnection();

	void Start();
	void Stop();

	void Send(TcpPacket* packet, size_t packetSize);

 	boost::asio::ip::tcp::socket& GetSocket() { return *socketPtr_; }

private:
	void Receive();
	void Close();

	void OnConnectCompleted(const boost::system::error_code& error);
	void OnReadCompleted(const boost::system::error_code& e, std::size_t bytes_transferred);
	void OnWriteCompleted(const boost::system::error_code& e);

	enum { kReadBufSize = 8192 };
	boost::asio::io_service& io_service_;
	boost::asio::io_service::strand strand_;
	std::shared_ptr<boost::asio::ip::tcp::socket> socketPtr_;
	boost::asio::ip::tcp::endpoint endpoint_;
	boost::array<char, kReadBufSize> buffer_;

	TcpIncomingPacketProcessor packetProcessor_;
	TcpConnectionEventHandler* eventHandler_;
};

